package io.terminus.lego.shinda.service.service

import io.terminus.lego.shinda.service.dao.UserOauthRelationRepository
import io.terminus.lego.shinda.service.dao.UserRepository
import io.terminus.lego.shinda.service.model.User
import io.terminus.lego.shinda.service.model.UserOauthRelation
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.domain.Example
import org.springframework.stereotype.Component
import org.springframework.transaction.annotation.Transactional
import java.util.*

/**
 * @author wangmeng
 * @date 2018/4/14
 */
@Component
@Transactional
class UserService @Autowired constructor(val userRepository: UserRepository,
                                         val relationRespository: UserOauthRelationRepository) {
    companion object {
        val USERNAME_PREFIX = "uc_"
        fun getOneUsername(providerId: String, providerUserId: String): String = USERNAME_PREFIX + providerId + "_" + providerUserId

    }

    fun create() {
        val userOauthRelation = UserOauthRelation(userId = 123L, providerId = "123", providerUserId = "123")
        relationRespository.save(userOauthRelation)
    }

    fun createByPhone(phone: String): User {
        val user = User(phone = phone, username = UUID.randomUUID().toString(), createdAt = Date(), nickName = "mobile_" + phone)
        return userRepository.save(user)
    }

    fun createByEmail(email: String): User {
        val user = User(email = email, username = UUID.randomUUID().toString(), createdAt = Date(), nickName = "email_" + email.subSequence(0, email.indexOf("@")))
        return userRepository.save(user)
    }

    fun findByProviderIdAndPorviderUserId(providerId: String, providerUserId: String): User? {
        val optional = relationRespository.findOne(Example.of(UserOauthRelation(providerId = providerId, providerUserId = providerUserId)))
        if (optional.isPresent) {
            return userRepository.getOne(optional.get().userId!!)
        }
        return null
    }

    fun createByProviderUser(providerId: String, providerUserId: String, nickName: String, avatarUrl: String,
                             orignalJson: String): User {
        val username = UserService.getOneUsername(providerId, providerUserId)
        val user = User(
                nickName = nickName,
                avatarUrl = avatarUrl,
                username = username,
                createdAt = Date())
        userRepository.save(user)

        val relation = UserOauthRelation(
                providerUserId = providerUserId,
                providerId = providerId,
                userId = user.id,
                originalJson = orignalJson,
                createdAt = Date())
        relationRespository.save(relation)
        return user
    }

    fun createRelation(userId: Long, providerId: String, providerUserId: String, nickName: String, avatarUrl: String,
                       orignalJson: String): Boolean {

        val relation = UserOauthRelation(
                providerUserId = providerUserId,
                providerId = providerId,
                userId = userId,
                originalJson = orignalJson,
                createdAt = Date())
        relationRespository.save(relation)
        return true
    }

    fun findUserById(id: Long): User? {
        return userRepository.getOne(id)
    }

    fun findUserByUsername(username: String): User? {
        val user = User(username = username)
        val optional = userRepository.findOne(Example.of(user))
        if (optional.isPresent) {
            return optional.get()
        }
        return null
    }

    fun findUserByEmail(email: String): User? {
        val user = User(email = email)
        val optional = userRepository.findOne(Example.of(user))
        if (optional.isPresent) {
            return optional.get()
        }
        return null
    }

    fun findUserByPhone(phone: String): User? {
        val user = User(phone = phone)
        val optional = userRepository.findOne(Example.of(user))
        if (optional.isPresent) {
            return optional.get()
        }
        return null
    }
}